package com.drako.tdgdx.logic;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.math.Plane;
import com.badlogic.gdx.math.Vector3;
import com.drako.tdgdx.helper.GlobalHelper;
import com.drako.tdgdx.helper.MeshObject;

public class PlayingFieldDiffusion {
	private int[][] smell;
	// if true then there is something
	private boolean[][] collision;

	private int targetX;
	private int targetY;
	
	private MeshObject[][] tiles;
	
	private int strengthSteps = 7;

	private class RealIntegerWrapper {
		public int i;

		public RealIntegerWrapper(int i) {
			this.i = i;
		}

		public String toString() {
			return "" + i;
		}
	}

	public PlayingFieldDiffusion(int width, int height, int targetX, int targetY) {
		
		GlobalHelper.fieldWidth = width;
		GlobalHelper.fieldHeight = height;
		smell = new int[width][height];
		collision = new boolean[width][height];
		tiles = new MeshObject[width][height];
		this.setTargetX(targetX);
		this.setTargetY(targetY);
		long time = System.nanoTime();
		setSmellIterative(targetX, targetY, 255);
		time = System.nanoTime() - time;
		Gdx.app.log("setSmell init", "" + time);
		time = System.nanoTime();
		initTiles();
		time = System.nanoTime() - time;
		Gdx.app.log("initTiles init", "" + time);
		
	}

	public void render(GL10 gl) {
		for (int i = 0; i < tiles.length; i++) {
			for (int j = 0; j < tiles[i].length; j++) {
				tiles[i][j].render(gl);
			}
		}
	}

	public void initTiles() {
		for (int i = 0; i < tiles.length; i++) {
			for (int j = 0; j < tiles[i].length; j++) {
				tiles[i][j] = new MeshObject(i *

				GlobalHelper.TILESIZE, j * GlobalHelper.TILESIZE,

				GlobalHelper.TILESIZE, GlobalHelper.TILESIZE, smell

				[i][j], smell[i][j], smell[i][j], 255);
			}
		}
	}

	// only for debug
	public void displaySmell() {
		for (int i = 0; i < tiles.length; i++) {
			for (int j = 0; j < tiles[i].length; j++) {
				tiles[i][j].changeColor(smell[i][j], smell[i][j], smell[i][j], 255);
			}
		}
	}

	// public void setSmellRek(int x, int y, int strength) {
	// // if the x or y are bigger or smaller than the playfield Arrays
	// if (x >= smell.length || y >= smell[0].length || x<0||y<0) {
	// return;
	// }
	//
	//
	// if (collision[x][y] || smell[x][y] >strength-10) {
	//
	// return;
	// }
	// smell[x][y] = strength;
	// setSmell(x-1,y,strength-strengthSteps);
	// setSmell(x+1,y,strength-strengthSteps);
	// setSmell(x,y-1,strength-strengthSteps);
	// setSmell(x,y+1,strength-strengthSteps);
	//
	//
	//
	// setSmellRek(x - 1, y+1, strength - strengthSteps);
	// setSmellRek(x+1, y + 1, strength - strengthSteps);
	// setSmellRek(x + 1, y-1, strength - strengthSteps);
	// setSmellRek(x-1, y - 1, strength - strengthSteps);
	//
	// }

	public void setSmellIterative(int x, int y, int strength) {
		int listSize = (GlobalHelper.fieldHeight * GlobalHelper.fieldWidth);

		int[] difArray1 = new int[listSize];
		int[] difArray2 = new int[listSize];
		RealIntegerWrapper nextIdx1 = new RealIntegerWrapper(0);
		RealIntegerWrapper nextIdx2 = new RealIntegerWrapper(0);

		setSmell(x, y, strength, difArray1, nextIdx1);
		// if addtional add setsmell
		// setSmell(0, 0, strength, difArray1, nextIdx1);
		// setSmell(19, 11, strength, difArray1, nextIdx1);
		// Gdx.app.log("setSmellIt", "" + nextIdx1);
		while (nextIdx1.i > 0) {
			nextIdx2.i = 0;
			for (int i = 0; i < nextIdx1.i; i++) {

				int tmp = difArray1[i];
				int iy = tmp / GlobalHelper.fieldWidth;
				int ix = tmp % GlobalHelper.fieldWidth;
				// Gdx.app.log("setSmellit1", x+","+y+"!"+ix+","+iy);
				propagateSmell(ix, iy, difArray2, nextIdx2);
				// Gdx.app.log("setSmellIt1", "" + i + "-->" + nextIdx2);
			}
			nextIdx1.i = 0;
			for (int i = 0; i < nextIdx2.i; i++) {
				int tmp = difArray2[i];
				int iy = tmp / GlobalHelper.fieldWidth;
				int ix = tmp % GlobalHelper.fieldWidth;
				// Gdx.app.log("setSmellit2", x+","+y+"!"+ix+","+iy);
				propagateSmell(ix, iy, difArray1, nextIdx1);
				// Gdx.app.log("setSmellIt2", "" + i + "-->" + nextIdx1);

			}

		}
		

		// propagateSmell(x, y);
		//
		// for(int i =y;i<smell[x].length;i++){
		// propagateSmell(x,i);
		// }
		// for(int i =y;i>=0;i--){
		// propagateSmell(x,i);
		// }
		// for(int i=x+1;i<smell.length;i++){
		// for (int j = 0; j < smell[i].length; j++) {
		// propagateSmell(i,j);
		//
		// }
		// }
		// for(int i=x-1;i>=0;i--){
		// for (int j = 0; j < smell[i].length; j++) {
		// propagateSmell(i,j);
		// }
		// }
		//
		//
		// for (int i = smell.length-1; i >= 0; i--) {
		// for (int j = smell[i].length-1; j >=0 ; j--) {
		// if(smell[i][j]<=0){
		// continue;
		// }
		// propagateSmell(i,j);
		// }
		// }

	}

	public void propagateSmell(int x, int y, int[] difArray,
			RealIntegerWrapper nextIdx) {
		if (x >= smell.length || y >= smell[0].length || x < 0 || y < 0
				|| collision[x][y]) {
			return;
		}
		if (smell[x][y] > 0) {
			int strength = smell[x][y] - strengthSteps;
			setSmell(x + 1, y, strength, difArray, nextIdx);
			setSmell(x - 1, y, strength, difArray, nextIdx);
			setSmell(x, y + 1, strength, difArray, nextIdx);
			setSmell(x, y - 1, strength, difArray, nextIdx);
			// Gdx.app.log("propSmell", "next" + nextIdx);
		}

	}

	public void setSmell(int x, int y, int strength, int[] difArray,
			RealIntegerWrapper nextIdx) {
		if (x >= smell.length || y >= smell[0].length || x < 0 || y < 0) {
			return;
		}
		if (collision[x][y] || smell[x][y] > 0) {
			return;
		}
		smell[x][y] = strength;
		// Gdx.app.log("setSmell", "cur" + nextIdx);
		difArray[nextIdx.i] = x + y * GlobalHelper.fieldWidth;
		nextIdx.i++;
		// Gdx.app.log("setSmell", "next" + nextIdx);

	}

	public int[][] getSmell() {
		return smell;
	}

	public void resetSmell() {
		for (int i = 0; i < smell.length; i++) {
			for (int j = 0; j < smell[i].length; j++) {
				smell[i][j] = 0;
			}
		}
	}

	public boolean[][] getCollision() {
		return collision;
	}

	public void setTargetX(int targetX) {
		this.targetX = targetX;
	}

	public int getTargetX() {
		return targetX;
	}

	public void setTargetY(int targetY) {
		this.targetY = targetY;
	}

	public int getTargetY() {
		return targetY;
	}


}
